package com.eol.web.controller.member;

import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import com.alibaba.fastjson.JSONObject;
import com.eol.common.annotation.HttpApi;
import com.eol.common.base.BaseResponse;
import com.eol.common.base.BaseResponseCode;
import com.eol.common.exception.BaseException;
import com.eol.common.jwt.JwtUtils;
import com.eol.common.jwt.TokenData;
import com.eol.common.sequence.Sequence;
import com.eol.common.sequence.SequenceGen;
import com.eol.common.utils.StringUtils;
import com.eol.entity.dto.wx.WechatUserAuthDto;
import com.eol.entity.dto.wx.WechatUserInfoDto;
import com.eol.entity.po.member.ZMember;
import com.eol.service.member.ZMemberService;
import com.eol.service.wx.WechatMpService;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;

/**
 * LoginController
 *
 * @author liulinhui
 * @email 1249055292@qq.com
 * @date 2020/6/1 21:34
 */
@RequestMapping
@RestController
public class LoginController {

    @Resource
    private ZMemberService zMemberService;
    @Resource
    private SequenceGen sequenceGen;
    @Resource
    private Sequence sequence;
    @Resource
    private JwtUtils jwtUtils;
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private WechatMpService wechatMpService;

    @RequestMapping(value = "register", method = RequestMethod.POST)
    @HttpApi(name = "用户注册", login = false)
    public BaseResponse register(@RequestBody @Valid ZMember.RegisterVo registerVo) {
        if (!StringUtils.isPhoneNum(registerVo.getPhone()))
            throw new BaseException(BaseResponseCode.PHONE_FORMAT_FAILED);
        String code = redisTemplate.opsForValue().get(registerVo.getUuid());
        if (!registerVo.getCode().equalsIgnoreCase(code)) {
            throw new BaseException(BaseResponseCode.CODE_VERIFY_FAILED);
        }
        //判断手机号码是否已经注册
        List<ZMember> list = zMemberService.selectList(ZMember.builder().phone(registerVo.getPhone()).build());
        if (null != list && list.size() > 0) {
            throw new BaseException(BaseResponseCode.PHONE_ALREADY_EXIT);
        }
        //生成唯一的邀请码
        String inviteCode = "";
        int retryNum = 10;
        for (int i = 0; i < retryNum; i++) {
            inviteCode = RandomStringUtils.randomNumeric(8);
            List<ZMember> zMemberList = zMemberService.selectList(ZMember.builder().inviteCode(inviteCode).build());
            if (null == zMemberList || zMemberList.size() < 1) {
                break;
            }
        }
        if ("".equalsIgnoreCase(inviteCode)) throw new BaseException("系统异常，请稍后再试！");
        String userId = sequenceGen.genUserId();
        long v = sequence.nextId();
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        zMemberService.insertSelective(ZMember.builder()
                .id(userId)
                .phone(registerVo.getPhone())
                .password(md5.digestHex(registerVo.getPassword()))
                .openid(registerVo.getOpenid())
                .createTime(new Date())
                .inviteMember(registerVo.getInviteMember())
                .avatar(registerVo.getAvatar())
                .email(registerVo.getEmail())
                .inviteCode(inviteCode)
                .userName(registerVo.getUserName())
                .build());
        String token = jwtUtils.generateToken(TokenData.builder()
                .userId(userId)
                .phoneNum(registerVo.getPhone())
                .t(System.currentTimeMillis())
                .v(v)
                .build());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("token", token);
        jsonObject.put("refreshToken", v);
        redisTemplate.delete(registerVo.getUuid());
        return BaseResponse.OK(jsonObject);
    }

    @RequestMapping(value = "login", method = RequestMethod.POST)
    @HttpApi(name = "用户登录", login = false)
    public BaseResponse login(@RequestBody @Valid ZMember.LoginVo loginVo) {
        if (!StringUtils.isPhoneNum(loginVo.getPhone()))
            throw new BaseException(BaseResponseCode.PHONE_FORMAT_FAILED);
        List<ZMember> list = zMemberService.selectList(ZMember.builder().phone(loginVo.getPhone()).build());
        if (null == list || list.size() < 1) {
            throw new BaseException(BaseResponseCode.PHONE_NONENTITY_FAILED);
        }
        ZMember zMember = list.get(0);
        if (StringUtils.isEmpty(loginVo.getPassword()) && (StringUtils.isEmpty(loginVo.getUuid()) || StringUtils.isEmpty(loginVo.getCode())))
            throw new BaseException("参数错误");
        //密码登录
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        if (StringUtils.isNotBlank(loginVo.getPassword()) && !md5.digestHex(loginVo.getPassword()).equalsIgnoreCase(zMember.getPassword())) {
            throw new BaseException(BaseResponseCode.PASSWORD_ISNULL_FAILED);
        }
        //手机号码登录
        if (StringUtils.isNotBlank(loginVo.getUuid())) {
            String code = redisTemplate.opsForValue().get(loginVo.getUuid());
            if (!loginVo.getCode().equalsIgnoreCase(code)) {
                throw new BaseException(BaseResponseCode.CODE_VERIFY_FAILED);
            }
        }
        //如果携带了openid更新用户信息
        if (StringUtils.isNotNullOrEmpty(loginVo.getOpenid())) {
            zMemberService.updateSelectiveById(ZMember.builder()
                    .id(zMember.getId())
                    .openid(loginVo.getOpenid())
                    .avatar(loginVo.getAvatar())
                    .userName(loginVo.getUserName())
                    .build());
        }
        JSONObject jsonObject = new JSONObject();
        long v = sequence.nextId();
        String token = jwtUtils.generateToken(TokenData.builder()
                .userId(zMember.getId())
                .phoneNum(zMember.getPhone())
                .t(System.currentTimeMillis())
                .v(v)
                .build());
        jsonObject.put("token", token);
        jsonObject.put("refreshToken", v);
        return BaseResponse.OK(jsonObject);
    }

    @RequestMapping(value = "loginByCode", method = RequestMethod.GET)
    @HttpApi(name = "微信根据code获取openid", login = false)
    public BaseResponse loginByCode(@RequestParam("code") String code) {
        WechatUserAuthDto wechatUserAuthDto = wechatMpService.getAccessTokenByCode(code);
        //判断openid是不是已经注册了
        ZMember zMember = zMemberService.selectOne(ZMember.builder()
                .openid(wechatUserAuthDto.getOpenid())
                .build());
        if (null == zMember) {
            WechatUserInfoDto wechatUserInfoDto = wechatMpService.oauth2getUserInfo(wechatUserAuthDto.getOpenid(), wechatUserAuthDto.getAccess_token());
            return new BaseResponse(wechatUserInfoDto);
        }
        JSONObject jsonObject = new JSONObject();
        long v = sequence.nextId();
        String token = jwtUtils.generateToken(TokenData.builder()
                .userId(zMember.getId())
                .phoneNum(zMember.getPhone())
                .t(System.currentTimeMillis())
                .v(v)
                .build());
        jsonObject.put("token", token);
        jsonObject.put("refreshToken", v);
        return BaseResponse.OK(jsonObject);
    }

}
